package com.zyk.scaffold.core.config.api;

import com.zyk.scaffold.core.domain.ApiMateInfo;
import com.zyk.scaffold.common.utils.ArrayUtils;
import com.zyk.scaffold.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.reactive.result.method.RequestMappingInfo;
import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.util.pattern.PathPattern;

import java.lang.reflect.Method;
import java.util.*;

/**
 * 应用服务 API
 */
public class ReactiveApiBuildHandler implements ApiBuildHandler {

    private RequestMappingHandlerMapping mapping;

    public ReactiveApiBuildHandler(RequestMappingHandlerMapping mapping) {
        this.mapping = mapping;
    }

    @Override
    public List<ApiMateInfo> buildApis() {
        List<ApiMateInfo> apis = new ArrayList<>();
        HashMap<String, List<ApiMateInfo>> handlerMapping = new HashMap<>();
        HashMap<String, String> mapClassName2Des = new HashMap<>();
        // 获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        // 遍历服务接口信息，筛选符合条件的数据
        map.forEach((mappingInfo, handlerMethod) -> {
            // 类
            Class<?> controllerClass = handlerMethod.getBeanType();
            // 包路径
            String classPackage = controllerClass.getName();
            if (verifyClassPackageHasProperties(classPackage, "com.micro.**.controller.**")) {
                // 方法
                Method method = handlerMethod.getMethod();
                ApiOperation apiOperation = AnnotatedElementUtils.findMergedAnnotation(method, ApiOperation.class);
                Api api = AnnotatedElementUtils.findMergedAnnotation(controllerClass, Api.class);
                if(apiOperation == null){
                    return;
                }
                // 获取方法路径
                String[] methodPaths = mappingInfo.getPatternsCondition().getPatterns().stream().map(PathPattern::getPatternString).toArray(String[]::new);
                // 生成数据
                ApiMateInfo apiMateInfo = new ApiMateInfo(classPackage + "#" + method.getName(), methodPaths[0], apiOperation.value(), null);
                List<ApiMateInfo> apiMateInfos = handlerMapping.get(classPackage);
                if(null == apiMateInfos){
                    apiMateInfos = new ArrayList<>();
                    handlerMapping.put(classPackage, apiMateInfos);
                }
                apiMateInfos.add(apiMateInfo);
                String pdes = api == null ? classPackage : Optional.ofNullable(api.value()).filter(StringUtils::isNotEmpty).orElse(ArrayUtils.get(api.tags(), 0));
                mapClassName2Des.put(classPackage, pdes);

            }
        });
        for (Map.Entry<String, String> stringStringEntry : mapClassName2Des.entrySet()) {
            String key = stringStringEntry.getKey();
            String value = stringStringEntry.getValue();

            List<ApiMateInfo> apiMateInfos = handlerMapping.get(key);
            if(apiMateInfos == null){
                apiMateInfos = Collections.emptyList();
            }
            apiMateInfos.forEach(item -> {
                item.setDes("[" + value + "]--" + item.getDes());
            });
            apis.add(new ApiMateInfo(key, null, value, apiMateInfos));
        }
        return apis;
    }
}
